package com.kexio.security.service.impl;

import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.kexio.core.security.context.UserContext;
import com.kexio.core.security.context.UserContextHolder;
import com.kexio.core.security.service.RbacService;
import com.kexio.security.domain.Permission;
import com.kexio.security.domain.Role;
import com.kexio.security.service.PermissionRepository;
import com.kexio.security.service.RoleRepository;
import com.kexio.security.service.SecurityUserContextService;

/**
 * Security模块RBAC权限控制服务实现
 * 
 * @author kexio
 */
@Service
public class SecurityRbacServiceImpl implements RbacService {

    private static final Logger log = LoggerFactory.getLogger(SecurityRbacServiceImpl.class);

    private final SecurityUserContextService userContextService;
    private final RoleRepository roleRepository;
    private final PermissionRepository permissionRepository;

    public SecurityRbacServiceImpl(SecurityUserContextService userContextService,
                                  RoleRepository roleRepository,
                                  PermissionRepository permissionRepository) {
        this.userContextService = userContextService;
        this.roleRepository = roleRepository;
        this.permissionRepository = permissionRepository;
    }

    @Override
    public boolean hasRole(Long userId, String role) {
        if (userId == null || role == null) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.hasRole(role);
        } catch (Exception e) {
            log.warn("检查用户角色失败: userId={}, role={}, error={}", userId, role, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean hasRole(String role) {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.hasRole(role);
    }

    @Override
    public boolean hasAnyRole(Long userId, String... roles) {
        if (userId == null || roles == null || roles.length == 0) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.hasAnyRole(roles);
        } catch (Exception e) {
            log.warn("检查用户角色失败: userId={}, roles={}, error={}", userId, roles, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean hasAnyRole(String... roles) {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.hasAnyRole(roles);
    }

    @Override
    public boolean hasPermission(Long userId, String permission) {
        if (userId == null || permission == null) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.hasPermission(permission);
        } catch (Exception e) {
            log.warn("检查用户权限失败: userId={}, permission={}, error={}", userId, permission, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean hasPermission(String permission) {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.hasPermission(permission);
    }

    @Override
    public boolean hasAnyPermission(Long userId, String... permissions) {
        if (userId == null || permissions == null || permissions.length == 0) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.hasAnyPermission(permissions);
        } catch (Exception e) {
            log.warn("检查用户权限失败: userId={}, permissions={}, error={}", userId, permissions, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean hasAnyPermission(String... permissions) {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.hasAnyPermission(permissions);
    }

    @Override
    public boolean hasAllPermissions(Long userId, String... permissions) {
        if (userId == null || permissions == null || permissions.length == 0) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.hasAllPermissions(permissions);
        } catch (Exception e) {
            log.warn("检查用户权限失败: userId={}, permissions={}, error={}", userId, permissions, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean hasAllPermissions(String... permissions) {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.hasAllPermissions(permissions);
    }

    @Override
    public List<String> getUserRoles(Long userId) {
        if (userId == null) {
            return List.of();
        }

        try {
            List<Role> roles = roleRepository.findByUserId(userId);
            return roles.stream()
                    .map(Role::getRoleCode)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.warn("获取用户角色失败: userId={}, error={}", userId, e.getMessage());
            return List.of();
        }
    }

    @Override
    public List<String> getUserPermissions(Long userId) {
        if (userId == null) {
            return List.of();
        }

        try {
            List<Permission> permissions = permissionRepository.findByUserId(userId);
            return permissions.stream()
                    .map(Permission::getPermissionCode)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.warn("获取用户权限失败: userId={}, error={}", userId, e.getMessage());
            return List.of();
        }
    }

    @Override
    public boolean isAdmin(Long userId) {
        if (userId == null) {
            return false;
        }

        try {
            UserContext userContext = userContextService.loadUserContextById(userId);
            return userContext != null && userContext.isAdmin();
        } catch (Exception e) {
            log.warn("检查管理员权限失败: userId={}, error={}", userId, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean isAdmin() {
        UserContext context = UserContextHolder.getContext();
        return context != null && context.isAdmin();
    }

    @Override
    public boolean canAccess(Long userId, String resource, String action) {
        if (userId == null || resource == null || action == null) {
            return false;
        }

        // 构建权限码，例如：system:user:list
        String permissionCode = String.format("%s:%s", resource, action);
        
        // 首先检查是否为超级管理员
        if (isAdmin(userId)) {
            return true;
        }

        // 检查具体权限
        return hasPermission(userId, permissionCode);
    }

    @Override
    public boolean canAccess(String resource, String action) {
        UserContext context = UserContextHolder.getContext();
        if (context == null) {
            return false;
        }

        return canAccess(context.getUserId(), resource, action);
    }

    @Override
    public boolean canOperateData(Long userId, String dataType, Long dataId, String action) {
        if (userId == null || dataType == null || dataId == null || action == null) {
            return false;
        }

        // 构建数据权限码，例如：data:user:1:edit
        String permissionCode = String.format("data:%s:%s:%s", dataType, dataId, action);
        
        // 首先检查是否为超级管理员
        if (isAdmin(userId)) {
            return true;
        }

        // 检查具体数据权限
        return hasPermission(userId, permissionCode);
    }

    @Override
    public boolean canOperateData(String dataType, Long dataId, String action) {
        UserContext context = UserContextHolder.getContext();
        if (context == null) {
            return false;
        }

        return canOperateData(context.getUserId(), dataType, dataId, action);
    }
}
